package com.cm.projectx.job.worker;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.cm.projectx.entity.*;
import com.cm.projectx.mapper.PriceTaskMapper;
import com.cm.projectx.mapper.ProductInfoMapper;
import com.cm.projectx.mapper.TaskProcessRelationMapper;
import com.cm.projectx.service.IProductPriceReportDetailService;
import com.cm.projectx.service.IProductPriceReportService;
import com.cm.projectx.service.impl.PriceTaskServiceImpl;
import com.cm.projectx.util.HttpUtils;
import com.cm.projectx.vo.Monitors;
import com.cm.projectx.vo.ProductMonitorRelation;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.jetbrains.annotations.NotNull;
import org.quartz.CronExpression;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;

import static cn.hutool.core.date.DateUtil.format;
import static cn.hutool.core.date.DateUtil.formatDate;

@Component
public class HandlerPushPriceTaskWorker extends QuartzJobBean {

    private static final Logger logger = LoggerFactory.getLogger(HandlerPushPriceTaskWorker.class);

    @Autowired
    private PriceTaskMapper priceTaskMapper;

    @Autowired
    private HttpUtils httpUtils;

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private ProductInfoMapper productInfoMapper;

    @Autowired
    private TaskProcessRelationMapper taskProcessRelationMapper;

    @Autowired
    private IProductPriceReportService productPriceReportService;

    @Autowired
    private IProductPriceReportDetailService productPriceReportDetailService;

    @Autowired
    private PriceTaskServiceImpl priceTaskService;

    @Value("${spring.low.code.process.issue}")
    private String issueUrl;

    @Value("${spring.low.code.process.createBy}")
    private String createByUrl;
    /**
     * 执行某个任务下发的逻辑，周、旬、月的通用下发逻辑
     * @param context
     */
    @Override
    protected void executeInternal(@NotNull JobExecutionContext context) {
        // 1. 从JobDataMap中获取任务ID
        JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
        Integer taskId = jobDataMap.getInt("taskId");
        String token = jobDataMap.getString("token");
        logger.info("开始执行定时下发任务, taskId: {}", taskId);
        try {
            // 2. 根据任务ID查询任务详情
            PriceTask task = priceTaskMapper.selectById(taskId);
            if (task == null) {
                logger.error("未找到对应的价格任务, taskId: {}", taskId);
                return;
            }
            // 4. 查询需要下发的监测点关联信息
            String productMonitorRelations = task.getProductMonitorRelations();
            List<ProductMonitorRelation> productMonitorRelationsList = parseProductMonitorRelations(productMonitorRelations);
            if (productMonitorRelations == null || productMonitorRelations.isEmpty()) {
                logger.warn("任务没有配置监测点关联关系, 跳过执行, taskId: {}", taskId);
                return;
            }
            HashMap<String, List<ProductReq>> monitorMap = new HashMap<>();
            // 新增：存储监测点级别的Map
            HashMap<String, String> monitorLevelMap = new HashMap<>();
            // 获取解析价格类型列表（多选）
            String taskPriceType = task.getPriceType();
            List<String> priceTypes = JSON.parseArray(taskPriceType, String.class);

            for (ProductMonitorRelation productMonitorRelation : productMonitorRelationsList) {
                List<String> monitorIds = new ArrayList<>();
                List<Monitors> monitorsList = productMonitorRelation.getMonitors();
                if (monitorsList != null) {
                    for (Monitors monitor : monitorsList) {
                        if (monitor != null && monitor.getMonitorId() != null) {
                            monitorIds.add(monitor.getMonitorId());
                            monitorLevelMap.put(monitor.getMonitorId(), monitor.getMonitorLevel());
                        }
                    }
                }
                String productId = productMonitorRelation.getProductId();
                //商品
                LambdaQueryWrapper<ProductInfo> query = Wrappers.lambdaQuery();
                ProductInfo productInfo = productInfoMapper.selectOne(query.eq(ProductInfo::getId, productId));

                //类别
                LambdaQueryWrapper<ProductInfo> type = Wrappers.lambdaQuery();
                type.eq(ProductInfo::getId, productInfo.getParentId());
                ProductInfo productTypeInfo = productInfoMapper.selectOne(type);
                // 为每个价格类型创建商品请求对象
                for (String priceType : priceTypes) {
                    ProductReq productReq = new ProductReq();
                    //商品id
                    productReq.setProperty1756711574233(productMonitorRelation.getProductId());
                    //商品名称
                    productReq.setProperty1758014414555(productInfo.getName());
                    //商品类别
                    productReq.setInput1756697848650(productTypeInfo.getName());
                    //规格等级
                    productReq.setProperty1756698675664(productInfo.getKind());
                    //计量单位
                    productReq.setProperty1756698692357(productInfo.getUnit());
                    logger.info("定时任务商品处理逻辑开始执行，任务名称{}",task.getTaskName());
                    //todo商品价格问题
                    for (String monitorId : monitorIds) {
                        // 如果任务是周期触发，使用任务id、监测点id查询出对应的所有流程记录
                        LambdaQueryWrapper<TaskProcessRelation> query1 = Wrappers.lambdaQuery();
                        query1.eq(TaskProcessRelation::getTaskId, taskId)
                                .eq(TaskProcessRelation::getMonitorId, monitorId)
                                .orderByDesc(TaskProcessRelation::getStartTime); // 按照开始时间降序排序

                        List<TaskProcessRelation> taskProcessRelations = taskProcessRelationMapper.selectList(query1);
                        // 如果没有任何历史流程记录，预置上报表单时上期价格、当期价格均为0
                        if (taskProcessRelations == null || taskProcessRelations.isEmpty()) {
                            // 本期上期都设置为0
                            logger.info("第一次下发周期任务");
                            productReq.setDigit1756697848650((double) 0);
                            productReq.setProperty1756698796775(String.valueOf(0));
                            continue;
                        }
                        AtomicBoolean findProduct = new AtomicBoolean(false);
                        //循环流程，查到最近的一次填报记录
                        for (int i = 0; i < taskProcessRelations.size(); i++) {
                            //流程id此流程id为上一次监测点填报的主流程id
                            String processId = taskProcessRelations.get(i).getProcessId();
                            //获取物价报送主表信息
                            LambdaQueryWrapper<ProductPriceReport> query2 = Wrappers.lambdaQuery();
                            if (StringUtils.isNotBlank(processId)) {
                                query2.eq(ProductPriceReport::getProcessId, processId);
                            }
                            ProductPriceReport one = productPriceReportService.getOne(query2);
                            //通过主表Id关联子表ParentId获取物价报送子表信息
                            LambdaQueryWrapper<ProductPriceReportDetail> query3 = Wrappers.lambdaQuery();
                            if (one != null) {
                                query3.eq(ProductPriceReportDetail::getParentId, one.getId());
                            }
                            //获得上一次填报的所有商品采集信息
                            List<ProductPriceReportDetail> list = productPriceReportDetailService.list(query3);
                            logger.info("开始赋值上期商品值");
                            //匹配商品信息
                            list.forEach(item -> {
                                if (item != null) {
                                    if (item.getProductInfoId().equals(productId) && item.getMetricType().equals(priceType)) {

                                        //todo 上期价格(应改是最近一次流程填报对应商品的本期值吧？)
                                        //productReq.setDigit1756697848650(item.getDigit1756697848650());
                                        productReq.setDigit1756697848650(item.getProperty1756698796775());
                                        //本期价格
                                        productReq.setProperty1756698796775(String.valueOf(item.getProperty1756698796775()));
                                        //价格浮动
                                        productReq.setProperty1757408011440(item.getProperty1757408011440());
                                        //序号
                                        productReq.setSortKey((int) item.getSortKey());
                                        findProduct.set(true);
                                    }
                                }
                            });
                            if(findProduct.get()) {
                                break;
                            }
                        }

                        // 取最近一次的流程记录（排序后的第一条）
//                        TaskProcessRelation latestTaskProcessRelation = taskProcessRelations.get(0);
//                        //流程id此流程id为上一次监测点填报的主流程id
//                        String processId = latestTaskProcessRelation.getProcessId();
//                        //获取物价报送主表信息
//                        LambdaQueryWrapper<ProductPriceReport> query2 = Wrappers.lambdaQuery();
//                        if (StringUtils.isNotBlank(processId)) {
//                            query2.eq(ProductPriceReport::getProcessId, processId);
//                        }
//                        ProductPriceReport one = productPriceReportService.getOne(query2);
//                        //通过主表Id关联子表ParentId获取物价报送子表信息
//                        LambdaQueryWrapper<ProductPriceReportDetail> query3 = Wrappers.lambdaQuery();
//                        if (one != null) {
//                            query3.eq(ProductPriceReportDetail::getParentId, one.getId());
//                        }
//                        //获得上一次填报的所有商品采集信息
//                        List<ProductPriceReportDetail> list = productPriceReportDetailService.list(query3);
//                        logger.info("开始赋值上期商品值");
//                        //匹配商品信息
//                        list.forEach(item -> {
//                            if (item != null) {
//                                if (item.getProductInfoId().equals(productId) && item.getMetricType().equals(priceType)) {
//
//                                    //todo 上期价格(应改是最近一次流程填报对应商品的本期值吧？)
//                                    //productReq.setDigit1756697848650(item.getDigit1756697848650());
//                                    productReq.setDigit1756697848650(item.getProperty1756698796775());
//                                    //本期价格
//                                    productReq.setProperty1756698796775(String.valueOf(0));
//                                    //价格浮动
//                                    productReq.setProperty1757408011440(item.getProperty1757408011440());
//                                    //序号
//                                    productReq.setSortKey((int) item.getSortKey());
//                                }
//                            }
//                        });
                    }
                    //价格类型
                    productReq.setProperty1758074143230(priceType);
                    //三期新增浮动阈值
                    productReq.setProperty1758787587191(productMonitorRelation.getFloatingValue());
                    //备注
                    productReq.setProperty1757407929409(null);
                    //转换数据结构  变成以监测点为键的map
                    monitorIds.forEach(monitorId -> {
                        List<ProductReq> products = monitorMap.get(monitorId);
                        if (products == null) {
                            products = new ArrayList<>();
                            products.add(productReq);
                            monitorMap.put(monitorId, products);
                        } else {
                            products.add(productReq);
                        }
                    });
                }
            }
            //todo 检测点-商品
            monitorMap.forEach((monitorId, products) -> {
                try {
                    //根据监测点组织信息id获取对应监测点人员信息
                    String userId = getUserId(monitorId, token);
                    //组装请求信息
                    FormSubmitReq formSubmitReq = new FormSubmitReq();
                    formSubmitReq.setProcessCode("wjxxbs");
                    //存放监测点对应人员id
                    formSubmitReq.setCreator(userId);
                    formSubmitReq.setCommitFirstTask("0");
                    FormDataReq fromDataReq = new FormDataReq();
                    //存放监测点对应人员id
                    fromDataReq.setCreator(userId);
                    //采价市场(监测点)，传入部门ID。
                    fromDataReq.setSelectDepartment1758071937554(monitorId);
                    //周 旬 月
                    fromDataReq.setSelect1756456950574(task.getScheduleType());
                    //报价开始时间(如果为周期任务（非自定义）取任务下发时间,自定义任务则取定期采价时间的cron解析出最近的报价开始时间)
                    String customizeCron = task.getCustomizeCron();
                    String scheduleType = task.getScheduleType();
                    Date quoteStartTime;
                    if (StringUtils.equals(scheduleType, "自定义") && StringUtils.isNotBlank(customizeCron)) {
                        CronExpression cronExpression = new CronExpression(customizeCron);
                        Date now = new Date();
                        quoteStartTime = cronExpression.getNextValidTimeAfter(now);
                        String date = formatDate(quoteStartTime);
                        //报价开始时间
                        logger.info("自定义报价开始时间为{}",date);
                        fromDataReq.setDatePicker1757414426057(date);
                        //发起流程时的流程名称使用   任务名称|报价时间   拼接传给低代码20250926
                        formSubmitReq.setProcInstNamePrefix(task.getTaskName() + "|" + date);
                    } else {
                        String date = formatDate(new Date());
                        //报价开始时间
                        fromDataReq.setDatePicker1757414426057(date);
                        //发起流程时的流程名称使用   任务名称|报价时间   拼接传给低代码20250926
                        formSubmitReq.setProcInstNamePrefix(task.getTaskName() + "|" + date);
                    }
                    //报价结束时间
                    String taskTime = task.getTaskTime();
                    Date endTime = calculateEndTimeSimple(taskTime);

                    fromDataReq.setDateTimePicker1758071962673(format(endTime, "yyyy-MM-dd HH:mm:ss"));
                    //任务级别
                    fromDataReq.setInput1758071979910(task.getTaskLevel());
                    //监测点级别
                    fromDataReq.setInput1758072003434(monitorLevelMap.get(monitorId));
                    SubModelReq subModelReq = new SubModelReq();
                    subModelReq.setEditableTable1756697848650(products);
                    //组装
                    formSubmitReq.setFormData(fromDataReq);
                    fromDataReq.setSubModel(subModelReq);
                    String s = objectMapper.writeValueAsString(formSubmitReq);
                    logger.info("周期任务请求参数为：{}", s);
                    //发起流程调用, processId由低代码返回
                    String processId = submitProcess(issueUrl, token, formSubmitReq);
                    logger.info("接口调用成功流程id-{}", processId);
                    // 保存任务-流程关联关系
                    saveTaskProcessRelation(task, monitorId, formSubmitReq.getFormData(), processId);

                } catch (Exception e) {
                    logger.error("流程发起异常, 监测点：{}", monitorId, e);
                    //priceTaskService.removeById(taskId);
                    // 将异常包装后重新抛出
                    throw new RuntimeException("流程发起失败，监测点: " + monitorId, e);
                }
            });

            logger.info("定时任务执行完成, taskId: {}", taskId);
        } catch (Exception e) {
            logger.error("执行定时价格任务异常", e);
            //priceTaskService.removeById(taskId);
            // 将异常包装后重新抛出
            throw new RuntimeException("流程发起失败", e);
        }
    }


    /**
     * 保存任务流程关联关系
     */
    private void saveTaskProcessRelation(PriceTask task, String monitorId, FormDataReq formData, String processId) {
        TaskProcessRelation relation = new TaskProcessRelation();
        relation.setTaskId(task.getId());
        relation.setProcessId(processId);
        relation.setStartTime(formData.getDatePicker1757414426057());
        relation.setMonitorId(monitorId);
        relation.setEndTime(formData.getDateTimePicker1758071962673());
        taskProcessRelationMapper.insert(relation);
    }

    /**
     * 简化版的结束时间计算（仅支持小时和天单位）
     * @param taskTime 时间字符串，格式如 "1小时"、"2天" 等
     * @return 结束时间
     */
    private Date calculateEndTimeSimple(String taskTime) {
        if (taskTime == null || taskTime.trim().isEmpty()) {
            return new Date();
        }

        // 直接检查字符串结尾来确定单位
        if (taskTime.endsWith("小时")) {
            int hours = Integer.parseInt(taskTime.replace("小时", "").trim());
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(new Date());
            calendar.add(Calendar.HOUR_OF_DAY, hours);
            return calendar.getTime();
        } else if (taskTime.endsWith("天")) {
            int days = Integer.parseInt(taskTime.replace("天", "").trim());
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(new Date());
            calendar.add(Calendar.DAY_OF_MONTH, days);
            return calendar.getTime();
        }
        // 如果无法识别单位，默认使用当前时间
        return new Date();
    }

    /**
     * 将JSON字符串解析为List<ProductMonitorRelation>
     * @param jsonString JSON格式的字符串
     * @return List<ProductMonitorRelation>对象，如果解析失败返回空列表
     */
    private List<ProductMonitorRelation> parseProductMonitorRelations(String jsonString) {
        if (jsonString == null || jsonString.trim().isEmpty()) {
            return Collections.emptyList();
        }
        try {
            // 使用Jackson将JSON字符串转换为List
            return objectMapper.readValue(
                    jsonString,
                    objectMapper.getTypeFactory().constructCollectionType(
                            List.class, ProductMonitorRelation.class
                    )
            );
        } catch (Exception e) {
            logger.error("解析产品监测点关系JSON失败: {}", jsonString, e);
            return Collections.emptyList();
        }
    }


    //检测点对应用户信息处理
    public String getUserId(String key,String token) {
        try {
            // 构建请求参数
            Map<String, Object> params = new HashMap<>();
            params.put("parentId", key);
            params.put("status", 1);
            params.put("tenantId", 1);

            // 调用接口获取响应
            JSONObject responseJson = httpUtils.get(createByUrl,token,params, JSONObject.class);

            // 检查请求是否成功
            if (responseJson != null && responseJson.getBool("result")) {
                JSONArray dataArray = responseJson.getJSONArray("data");
                if (dataArray != null && !dataArray.isEmpty()) {
                    // 遍历查找第一个group=false的项
                    for (int i = 0; i < dataArray.size(); i++) {
                        JSONObject item = dataArray.getJSONObject(i);
                        if (item.containsKey("group") && !item.getBool("group")) {
                            return item.getStr("id");
                        }
                    }
                }
            }
            logger.warn("未找到符合条件的用户数据，parentId: {}", key);
            throw new RuntimeException("未找到符合条件的用户数据");
        } catch (Exception e) {
            // 处理异常
            logger.error("获取用户ID时出错: " + e.getMessage());
            throw new RuntimeException("获取用户ID时发生错误",e);
        }
    }



    public String submitProcess(String url,String token, FormSubmitReq formSubmitReq) {
        try {
            // 发送请求
            String jsonResponse = httpUtils.postJson(url, token,formSubmitReq, String.class);
            // 解析响应
            JsonNode rootNode = objectMapper.readTree(jsonResponse);

            // 检查API调用是否成功
            if (rootNode.has("result") && rootNode.get("result").asBoolean()) {
                // 提取processId (instanceId)
                JsonNode dataNode = rootNode.get("data");
                if (dataNode != null && dataNode.has("instanceId")) {
                    return dataNode.get("instanceId").asText();
                } else {
                    throw new RuntimeException("API响应中缺少data或instanceId字段");
                }
            } else {
                // 处理API调用失败的情况
                String errorCode = rootNode.has("errorCode") ? rootNode.get("errorCode").asText() : "未知错误";
                String errorMsg = rootNode.has("errorMsg") ? rootNode.get("errorMsg").asText() : "无错误信息";
                throw new RuntimeException("API调用失败: " + errorCode + " - " + errorMsg);
            }
        } catch (Exception e) {
            throw new RuntimeException("处理API响应时发生异常: " + e.getMessage(), e);
        }
    }

}
